
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>插入数据时扩容的重新hash是怎么做的？ - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>插入数据时扩容的重新hash是怎么做的？ - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在 Java 的 HashMap 中，什么条件下会触发扩容（resize）操作？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当 HashMap 的元素数量（size）超过了当前数组容量与负载因子（loadFactor，通常为 0.75）的乘积（即 threshold）时，会触发扩容操作。</div>
          </div>
          <div class="card-source">来源: 重新哈希的过程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">HashMap 扩容时，新数组的容量通常是如何确定的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">扩容操作会创建一个新的数组，其容量通常是旧数组容量的两倍。新数组的大小会保持为2的幂，以便于使用高效的位运算来计算索引。</div>
          </div>
          <div class="card-source">来源: 重新哈希的过程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是“重新哈希”（rehashing）？为什么在 HashMap 扩容时需要这个过程？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">重新哈希（rehashing）是指在扩容过程中，重新计算每个键的哈希值并将其重新分配到新数组位置的过程。这是必需的，因为新数组的长度与旧数组不同，导致用于计算索引的基准（length - 1）发生了变化，因此每个元素的位置都需要重新计算。</div>
          </div>
          <div class="card-source">来源: 重新哈希的过程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">HashMap 是如何通过哈希值（hash）和数组长度（length）来计算元素存放的索引位置的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">HashMap 通过一个通常定义为 `hash & (length - 1)` 的位运算来计算索引。这种方法等效于取模运算，但效率更高，前提是数组长度 `length` 必须是2的幂。</div>
          </div>
          <div class="card-source">来源: 重新哈希的过程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">请概述 HashMap 扩容过程中的三个关键步骤。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">HashMap 扩容的关键步骤包括：1. 创建一个容量是原数组两倍的新数组；2. 遍历旧数组中的每个节点，重新计算其在新数组中的位置，并将其插入；3. 所有元素重新分配完成后，将 HashMap 内部的 table 引用更新为指向这个新数组。</div>
          </div>
          <div class="card-source">来源: 扩容的关键步骤</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">源码</div>
          <div class="card-question">在 HashMap 的源码中，`resize` 方法的主要职责是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">源码</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`resize` 方法负责整个扩容流程的协调。它的主要职责包括：创建容量为旧容量两倍的新数组，调用 `transfer` 方法将旧数组的元素迁移到新数组，更新 `table` 引用指向新数组，并重新计算下一次扩容的阈值 `threshold`。</div>
          </div>
          <div class="card-source">来源: 源码分析</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">源码</div>
          <div class="card-question">在 HashMap 的源码中，`transfer` 方法在扩容过程中扮演了什么角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">源码</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`transfer` 方法的核心作用是数据迁移。它会遍历源数组（旧数组）中的每一个位置，并将该位置上的所有节点（包括链表或红黑树中的节点）逐一重新计算索引，然后放入新数组的相应位置。</div>
          </div>
          <div class="card-source">来源: 源码分析</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在扩容完成后，HashMap 内部会更新哪些重要的成员变量？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">在所有元素被迁移到新数组后，HashMap 会更新 `table` 引用，使其指向新创建的数组。同时，它还会根据新的容量和负载因子重新计算并更新 `threshold`（阈值）变量。</div>
          </div>
          <div class="card-source">来源: 源码分析</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">在将元素从旧数组移动到新数组时，具体的操作是怎样的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">该过程通过遍历旧数组实现。对于旧数组中的每个非空桶（bucket），会遍历其中的所有节点（Node）。对每个节点，使用新数组的容量重新计算其索引 `i`，然后将其以头插法的方式放入新数组 `newTable` 的 `newTable[i]` 位置。</div>
          </div>
          <div class="card-source">来源: 重新哈希的过程</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
